﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FairyGUI;
using DG.Tweening;
using UnityEngine;

namespace Model
{
    [ObjectEvent]
    public class SearchWindowComponentEvent : ObjectEvent<WindowManagerComponent>, IAwake<PlayerUIComponent>
    {
        public void Awake(PlayerUIComponent PlayerUI)
        {
            //Get().Awake();
            Get().Awake(PlayerUI);
        }
    }

    public class WindowManagerComponent : BattleEventComponent
    {
        PlayerUIComponent Onwer;
        public static SearchWindow searchWindow;
        public static DecideWindow decideWindow;
        public static PowerUseWindow powerUseWindow;
        public static AskWindow askWindow;
        public void Awake(PlayerUIComponent battlePlayer)
        {
            Awake();
            if (searchWindow==null) searchWindow = new SearchWindow();
            if (decideWindow == null) decideWindow = new DecideWindow();
            if (powerUseWindow == null) powerUseWindow = new PowerUseWindow();
            if (askWindow == null) askWindow = new AskWindow();
            Onwer = battlePlayer;
        }
        public override BattleEventType[] EventType { get; set; } = new BattleEventType[] { BattleEventType.ShowWindow };
        public override async Task RunEvent(BattleEventType eventType, FightModel fightModel, params object[] param)
        {
            WindowType windowType = (WindowType)param[0];
            switch (windowType)
            {
                case WindowType.Search:
                    await ShowSearchWindow(param);
                    break;
                case WindowType.Decide:
                    await ShowDecideWindow(param);
                    break;
                case WindowType.PowerUse:
                    await ShowPowerUseWindow(param);
                    break;
                case WindowType.Ask:
                    await ShowAskWindow(param);
                    break;
            }
        }

        async Task ShowAskWindow(params object[] param)
        {
            DecideInfo decideInfo = param[1] as DecideInfo;
            askWindow.Show();
            askWindow.SetAskInfo(decideInfo);
            await askWindow.WindowDelay();
        }
        async Task ShowSearchWindow(params object[] param)
        {
            SearchInfo searchInfo = param[1] as SearchInfo;
            searchWindow.Show();
            searchWindow.SetShowCard(searchInfo);
            await searchWindow.WindowDelay();
        }
        async Task ShowDecideWindow(params object[] param)
        {
            List<DecideInfo> list = param[1] as List<DecideInfo>;
            decideWindow.Show();
            foreach (var a in list)
            {
                decideWindow.AddDecide(a.CallBack, a.Describe);
            }
            await decideWindow.WindowDelay();
        }
        async Task ShowPowerUseWindow(params object[] param)
        {
            powerUseWindow.Show();
            PowerUseInfo powerUseInfo = param[1] as PowerUseInfo;
            powerUseWindow.SetUsePlayer(powerUseInfo.battlePlayer, powerUseInfo.PowerUse);
            powerUseWindow.SetCallBack(powerUseInfo.CallBack);
            await powerUseWindow.WindowDelay();
        }
    }
    public enum WindowType
    {
        Search,
        Decide,
        Ask,
        PowerUse,
    }

    public class AskWindow : GameWindow
    {
        protected override void OnInit()
        {
            contentPane = UIPackage.CreateObject("Battle", "AskWindow").asCom;
            Center();
            modal = true;
            contentPane.GetChild("n2").onClick.Add(Hide);
        }
        public void SetAskInfo(DecideInfo decideInfo)
        {
            contentPane.GetChild("n3").text = decideInfo.Describe;
            contentPane.GetChild("n1").onClick.Set(() =>
            {
                decideInfo.CallBack?.Invoke();
                Hide();
            });            
        }
    }

    public class SearchWindow : GameWindow
    {
        GList CardList;
        int ChooseNum;
        Func<List<BattleCard>, bool> Condition;
        //Action<List<BattleCard>> CallBack;
        protected override void OnInit()
        {
            contentPane = UIPackage.CreateObject("Battle", "SearchWindow").asCom;
            Center();
            modal = true;
            contentPane.GetChild("n3").onClick.Add(Hide);
            CardList = contentPane.GetChild("n1").asList;
            CardList.onClickItem.Add((x) =>
            {
                GButton g = x.data as GButton;
                if (!g.selected)
                {
                    g.selected = false;
                    ReAble();
                    return;
                }
                if (CardList.GetSelection().Count <= ChooseNum)
                {
                    g.selected = true;
                }
                else
                    g.selected = false;
                ReAble();
                //BattleCard battleCard = g.data as BattleCard;
            });
            contentPane.GetChild("n3").onClick.Add(Hide);
            //dragBounds = new Rect(0, 0, GRoot.inst.width, GRoot.inst.height);
        }

        void ReAble()
        {
            List<BattleCard> outlist = new List<BattleCard>();
            for (int i = 0; i < CardList.numChildren; i++)
            {
                if (CardList.GetChildAt(i).asButton.selected)
                    outlist.Add(CardList.GetChildAt(i).data as BattleCard);
            }
            contentPane.GetChild("n2").enabled = Condition(outlist);
            //Log.Debug(outlist.Count.ToString());
        }

        public void SetShowCard(SearchInfo searchInfo)
        {
            this.Condition = searchInfo.Condition;
            CardList.RemoveChildrenToPool();
            for (int i = 0; i < searchInfo.ShowCard.Count; i++)
            {
                GComponent g = CardList.AddItemFromPool().asCom;
                g.asButton.selected = false;
                BattleCard.SetCardToUI(g, searchInfo.ShowCard[i], true);
            }
            this.ChooseNum = searchInfo.MaxChooseNum;
            ReAble();
            contentPane.GetChild("n2").onClick.Set(() => {
                List<BattleCard> outlist = new List<BattleCard>();
                for (int i = 0; i < CardList.numChildren; i++)
                {
                    if (CardList.GetChildAt(i).asButton.selected)
                        outlist.Add(CardList.GetChildAt(i).data as BattleCard);
                }
                searchInfo.OnSure?.Invoke(outlist);
                Hide();
            });
        }
    }
    public class DecideWindow : GameWindow
    {
        int DecideNum;
        protected override void OnInit()
        {
            contentPane = UIPackage.CreateObject("Battle", "DecideWindow").asCom;
            Center();
            modal = true;
        }
        public DecideWindow ClearDecide()
        {
            DecideNum = 0;
            return this;
        }
        public DecideWindow AddDecide(Action CallBack, string Info)
        {
            DecideNum++;
            if (DecideNum > 3)
            {
                Log.Error("暂时只支持最多三个选项！！");
                return this;
            }
            GComponent g = contentPane.GetChild("n" + DecideNum).asCom;
            g.onClick.Set(() => {
                Hide();
                DecideNum = 0;
                CallBack?.Invoke();
            });
            g.text = Info;
            contentPane.GetController("c1").selectedIndex = DecideNum;
            return this;
        }
    }

    public class PowerUseWindow : GameWindow
    {
        GList powerList, powerCardList;
        GTextField NeedPower;
        int PowerCost;
        //int MaxPower, BrokenPower, Power;
        BattlePlayer battlePlayer;
        protected override void OnInit()
        {
            contentPane = UIPackage.CreateObject("Battle", "PowerWindow").asCom;
            Center();
            modal = true;
            powerList = contentPane.GetChild("n2").asList;
            powerCardList = contentPane.GetChild("n1").asList;
            NeedPower = contentPane.GetChild("n4").asTextField;
            //powerList.onClickItem.Add(PowListClick);
            powerCardList.onClick.Add(() => ReCalPowerUse());
            contentPane.GetChild("n6").onClick.Add(Hide);
            //dragBounds = new Rect(0, 0, GRoot.inst.width, GRoot.inst.height);
        }

        public void SetCallBack(Action action)
        {
            contentPane.GetChild("n5").onClick.Set(() =>
            {
                battlePlayer.Power = battlePlayer.Power - PowerCost + GetSelectionCount();
                for (int i = powerCardList.numChildren - 1; i >= 0; i--)
                {
                    if (powerCardList.GetChildAt(i).data == null) continue;
                    List<BattleCard> list = new List<BattleCard>();
                    if (powerCardList.GetChildAt(i).asButton.selected)
                    {
                        list.Add(battlePlayer[CardPlace.Power].Cards[i]);
                        //Log.Debug(((BattleCard)powerCardList.GetChildAt(i).data).InfoFlag);
                        //battlePlayer[CardPlace.Power].MoveCards(battlePlayer[CardPlace.Cemetery], battlePlayer[CardPlace.Power].Cards[i], CardPlace.Cemetery);
                    }
                    battlePlayer[CardPlace.Power].MoveCards(battlePlayer[CardPlace.Cemetery], list);
                }
                action?.Invoke();
                Hide();
            });
        }

        int GetSelectionCount()
        {
            int num = 0;
            for (int i = 0; i < powerCardList.numChildren; i++)
            {
                if (powerCardList.GetChildAt(i).data != null && powerCardList.GetChildAt(i).asButton.selected)
                    num++;
            }
            return num;
        }

        bool ReCalPowerUse()
        {
            int p = battlePlayer.Power - PowerCost + GetSelectionCount();
            //Log.Debug($"{PowerCost},{p},{battlePlayer.Power}");
            for (int i = 0; i < powerList.numChildren; i++)
            {
                GComponent item = powerList.GetChildAt(i).asCom;
                if (i < p)
                    item.GetController("c1").selectedIndex = 0;
                else if (i < battlePlayer.MaxPower - battlePlayer.BrokenPower)
                    item.GetController("c1").selectedIndex = 1;
                else
                    item.GetController("c1").selectedIndex = 2;
            }
            if (p < 0)
            {
                NeedPower.text = (-p).ToString();
            }
            else
            {
                NeedPower.text = "0";
            }
            //p = PowerCost - p;
            contentPane.GetChild("n5").enabled = p >= 0;
            return (p >= 0);
        }

        public void SetUsePlayer(BattlePlayer battlePlayer, int PowerCost)
        {
            for (int i = 0; i < powerCardList.numChildren; i++)
            {
                if (i < battlePlayer[CardPlace.Power].Cards.Count)
                    BattleCard.SetCardToUI(powerCardList.GetChildAt(i).asCom, battlePlayer[CardPlace.Power].Cards[i], true);
                else
                    BattleCard.SetCardToUI(powerCardList.GetChildAt(i).asCom, null);
                powerCardList.GetChildAt(i).asButton.selected = false;
            }
            this.PowerCost = PowerCost;
            this.battlePlayer = battlePlayer;
            ReCalPowerUse();
        }
    }

    public class GameWindow:Window
    {
        public async Task WindowDelay()
        {
            while (isShowing)
            {
                await Task.Delay(10);
            }
            return;
        }
        override protected void DoShowAnimation()
        {
            Center();
            SetScale(0.1f, 0.1f);
            SetPivot(0.5f, 0.5f);
            TweenScale(new Vector2(1, 1), 0.3f).SetEase(Ease.OutQuad).OnComplete(OnShown);
        }

        override protected void DoHideAnimation()
        {
            TweenScale(new Vector2(0.1f, 0.1f), 0.3f).SetEase(Ease.OutQuad).OnComplete(HideImmediately);
        }
    }
}
